/*
    This file is part of Titan.

    Titan is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as 
    published by the Free Software Foundation, either version 3 of 
    the License, or (at your option) any later version.

    Titan is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Titan. If not, see <http://www.gnu.org/licenses/>.
*/

package titan;

import java.io.IOException;

import java.util.Observable;
import java.util.Observer;
import net.tinyos.message.MessageListener;
import titan.messages.SerialMsg;
import titan.mobile.TitanMobile;
import titancommon.Performance;
import titancommon.route.TitanRouter;

/**
 * Exchanges messages with the sensor network, be it a real 
 * physical one, or a simulation. This class is a wrapper for 
 * MoteIF, as it does not (yet?) support communication with 
 * TOSSIM in TinyOS 2.0.
 * 
 * @author Clemens Lombriser <lombriser@ife.ee.ethz.ch>
 * @author Tonio Gsell <tgsell@ee.ethz.ch>
 * 
 *
 *
 */


public class TitanCommunicate implements Observer{

    MessageListener m_Listener = null;
    private int m_Mode;
    
    public static final int TMOTE = 0;
    public static final int SIM = 1;
    public static final int BLUETOOTH = 2;
    public static final int TCP_ONLY = 3;
    public static final int DEFAULT = 2;

    public static final int TOS_BCAST_ADDR = 0xFFFF;

    /**
     * Instantiates a TitanCommunicate object
     * @param bSimulating Tells whether we are simulating or not
     */
    public TitanCommunicate( int mode ) {
        m_Mode = mode;

        if ( mode == BLUETOOTH) {
        }
        else if ( mode == TCP_ONLY ) {
        }
        else {
            System.out.println("TitanCommunicate: unsupported mode");
        }
        
    }

    /**
     * This method is only included for compatibility to the desktop
     * @param strChannel Channel name to monitor
     */
    public void SimAddChannel(String strChannel) {
    }

    /**
     * This method is only included for compatibility to the desktop
     * @param period time to advance simulation
     */
    public void SimContinue(float period) {
    }

    /**
     * Send m to moteId via this mote interface
     * @param moteId message destination
     * @param m message
     * @exception IOException thrown if message could not be sent
     */
    public boolean send(int moteId, SerialMsg m) {
        
        Performance.begin( "WSNSend message to " + moteId + " size: [" + m.get_length() + "]");

        // remove net_id from destination addr. for bt communication
        int addr = m.get_address();
        if ((addr != 0xFFFF) && (addr != -1)) {
          m.set_address(addr & TitanRouter.CLIENT_MASK);
        }
    	
    	try {
        TitanMobile.getBlueCom().send(m);
         //Thread.sleep(200);
      } catch (IOException e) {
        TitanMobile.getGUI().setDebugText(this.getClass().getName(), "send:send", e.toString());
      } //catch (InterruptedException e) {}
    	
		return true;
    }
    
    public boolean isConnected() {
      if (m_Mode == TCP_ONLY)
        return true;

    	return TitanMobile.getBlueCom().isConnected();
    }

    
    /**
     * Register a listener for given messages type. The message m should be
     * an instance of a subclass of Message (generated by mig). When a
     * message of the corresponding type is received, a new instance of m's
     * class is created with the received message as data. This message is
     * then passed to the given MessageListener.
     * 
     * Note that multiple MessageListeners can be registered for the same
     * message type, and in fact each listener can use a different template
     * type if it wishes (the only requirement is that m.getType() matches
     * the received message).
     * WARNING: This only holds true for the real implementation. For 
     * simulation, only one listener is supported!!!
     *
     * @param m message template specifying which message to receive
     * @param l listener to which received messages are dispatched
     */
    synchronized public void registerListener(SerialMsg template, MessageListener listener) {
        
/*        if (m_MoteIF != null ) {
            m_MoteIF.registerListener(template,listener);
        } else {
*/
    	m_Listener = listener;
//        }
        
    }
    
    /**
     * Deregister a listener for a given message type.
     * @param m message template specifying which message to receive
     * @param l listener to which received messages are dispatched
     */
    synchronized public void deregisterListener(SerialMsg template, MessageListener listener) {
        
/*        if (m_MoteIF != null ) {
            m_MoteIF.deregisterListener(template,listener);
        } else {
        */
            if (m_Listener == listener) m_Listener = null;
/*        }
*/        
    }

    public void update(Observable arg0, Object arg1) {

        if( m_Listener != null ) {
            m_Listener.messageReceived(-1, (SerialMsg)arg1);
        }
    }
    

}
